﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace SmartMathLibrary.Storage
{
    /// <summary>
    /// Defines the lock status of a storage.
    /// </summary>
    public enum StorageLockStatus
    {
        /// <summary>
        /// The storage is locked. This means, that nobody is allowed to add
        /// new position data to the storage.
        /// </summary>
        Locked = 0,
        /// <summary>
        /// The storage is unlocked. This means, that everyone is able to
        /// add new position data to the storage.
        /// </summary>
        Unlocked = 1
    }

    /// <summary>
    /// This class represents a specialization of an abstract storage. The special function 
    /// of this storage is, that the storage is able to be locked. If the storage is locked, 
    /// no points can be added to the storage. If the storage is unlocked it can be used like a 
    /// normal point storage.
    /// </summary>
    [Serializable]
    public class LockablePointStorage : PointStorage
    {
        /// <summary>
        /// The lock status of the storage.
        /// </summary>
        private StorageLockStatus storageLockStatus;

        /// <summary>
        /// Initializes a new instance of the <see cref="LockablePointStorage"/> class.
        /// </summary>
        /// <param name="size">The size of the storage.</param>
        public LockablePointStorage(int size)
            : base(size)
        {
            this.storageLockStatus = StorageLockStatus.Unlocked;
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="LockablePointStorage"/> class.
        /// </summary>
        /// <param name="size">The size of the storage.</param>
        /// <param name="storageLockStatus">The lock status of the storage.</param>
        public LockablePointStorage(int size, StorageLockStatus storageLockStatus)
            : base(size)
        {
            this.storageLockStatus = storageLockStatus;
        }

        /// <summary>
        /// Gets or sets the lock status of the storage.
        /// </summary>
        /// <value>The lock status of the storage.</value>
        public StorageLockStatus StorageLockStatus
        {
            get { return storageLockStatus; }
            set { storageLockStatus = value; }
        }

        /// <summary>
        /// This method adds a new point to the current storage. If the maximum capacity of the 
        /// storage is exceeded, it will automatically overwrite the smallest point of the storage.
        /// If the lock status of the storage is locked, this method will throw an StorageLockedException.  
        /// </summary>
        /// <param name="item">The point item, which should be add to the storage.</param>
        public override void AddPoint(StoragePoint item)
        {
            if (this.storageLockStatus == StorageLockStatus.Unlocked)
            {
                if (this.fillSize < this.cacheSize)
                {
                    this.fillSize++;
                }

                base.AddPoint(item);
            }

            throw new StorageLockedException("Storage is currently locked.");
        }
    }
}